package com.alex.monitor.core.rule.impl;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.util.StrUtil;
import com.alex.monitor.core.annotation.MethodMonitor;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * 基于时间计数的监控规则类
 *
 * @author Alex.Liu
 * @date: 2025-02-17 12:21
 * @since 1.0.0
 */
public class TimeCountBasedMonitorRule extends DefaultMonitorRule {

    /**
     * 默认十次
     */
    private static final int MAX = 10;

    /**
     * 计次
     */
    private static final TimedCache<String, Integer> CACHE = CacheUtil.newTimedCache(TimeUnit.HOURS.toMillis(1));

    /**
     * 当在1小时内调用次数超过10次，则触发监控
     *
     * @param method     方法名称
     * @param annotation 方法监控注解
     * @param result     方法执行结果
     * @return
     */
    @Override
    public boolean match(Method method, MethodMonitor annotation, Object result) {
        String key = annotation.groupId();
        if (StrUtil.isBlank(annotation.groupId())) {
            key = method.getDeclaringClass().getName() + "." + method.getName() + "." + annotation.uniqueId();
        }
        if (super.match(method, annotation, result)) {
            Integer count = CACHE.get(key);
            if (count == null) {
                count = 1;
            } else {
                count++;
            }
            CACHE.put(key, count);
            if (count > MAX) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 当在1小时内调用次数超过10次，则触发监控
     *
     * @param method     方法名称
     * @param annotation 方法监控注解
     * @param exception  抛出的异常
     * @return
     */
    @Override
    public boolean match(Method method, MethodMonitor annotation, Throwable exception) {
        String key = annotation.groupId();
        if (StrUtil.isBlank(annotation.groupId())) {
            key = method.getDeclaringClass().getName() + "." + method.getName() + "." + annotation.uniqueId();
        }
        if (super.match(method, annotation, exception)) {
            Integer count = CACHE.get(key);
            if (count == null) {
                count = 1;
            } else {
                count++;
            }
            CACHE.put(key, count);
            if (count > MAX) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }
}